package main

import (
	"fmt"
	//"golang.org/x/tour/pic"
	"strings"
	"math"
)

var q = make(chan int)

func say(string string, bg ...bool) {
	for i := 0; i < 5; i++ {
		fmt.Println(string)
	}
	if len(bg) > 0 && bg[0] {
		q <- 0
	}
}

// 指针的操作可修改值本身
func plus(i *int) {
	*i += 1
}

func tryPanic(string string) {
	panic("就是挂了给你看！" + string)
}

func main() {

	//panicRecoverDemo()
	//sliceDemo()
	//mapDemo()
	//chanDemo()
	//pic.Show(Pic)
	//stringFields()
	//fmt.Println(WordCount("Hello go go go !"))
	//closureDemo()
	fbDemo()
}

func panicRecoverDemo() {
	defer func() {
		// recover可以捕获panic输出的值
		// v的值是"尝试着一丝不挂给你看看~"
		v := recover()
		fmt.Println(v) // 尝试着一丝不挂给你看看~
	}()

	fmt.Println("Panic and recover test")
	panic("尝试着一丝不挂给你看看~")
}

func sliceDemo() {
	var s1 []int         // s1 is nil
	s2 := []int{}        // s2 is empty, but not nil, 编译器有告警
	s3 := make([]int, 0) // s3 is empty, but not nil, best practice

	fmt.Println(s1, s2, s3)
	fmt.Println("s1 == nil", s1 == nil) // true
	fmt.Println("s2 == nil", s2 == nil) // false
	fmt.Println("s3 == nil", s3 == nil) // false

	// 三种方式定义的slice都能append
	s1 = append(s1, 100)
	s2 = append(s2, 100)
	s3 = append(s3, 100)
	fmt.Println(s1, s2, s3) // [100] [100] [100]
}

func mapDemo() {
	var m1 map[int]string      // m1 is nil
	m2 := map[int]string{}     // m2 is empty, but not nil, 编译器无告警
	m3 := make(map[int]string) // m2 is empty, but not nil, best practice

	// m1[1] = "Hello" 无法赋值
	m2[1] = "Hello"
	m2[2] = "Go"
	m3[1] = "Hello"
	m3[2] = "Go"

	fmt.Println(m1, m2, m3)
}

func chanDemo() {
	c := make(chan int)

	// 使用go将以goroutine在后台运行
	go func() {
		for i := 0; i < 10; i++ {
			fmt.Println("in goroutine", i)
		}
		c <- 0
	}()

	// 等待goroutine的结束
	<-c
}

func Pic(dx, dy int) [][]uint8 {
	a := make([][]uint8, dy)
	for i := range a {
		a[i] = make([]uint8, dx)
		for j := range a[i] {
			a[i][j] = uint8(float64(i) * math.Log(float64(j)))
		}
	}
	return a
}

func stringFields() {
	fmt.Printf("Fields are: %q", strings.Fields("  foo bar  baz  foo "))
}

func WordCount(s string) map[string]int {
	a := strings.Fields(s)
	m := make(map[string]int)
	for _, v := range a {
		m[v]++
	}
	return m
}

func closureDemo() {
	type myFunc func(int) int
	adder := func() myFunc {
		sum := 0
		return func(x int) int {
			sum += x
			return sum
		}
	}
	// 函数 adder 返回一个闭包
	// 每个闭包都被绑定在其各自的 sum 变量上
	pos, neg := adder(), adder()
	for i := 1; i < 10; i++ {
		fmt.Println(pos(i), neg(-2*i))
	}
}

func fibonacci() func() int {
	a, b := 0, 1
	return func() (v int) {
		v, a, b = a, b, a+b
		return
	}
}

func fbDemo() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}
